/*
 * Copyright (C) 2010 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
/*
Taken from
http://android-touchexample.googlecode.com/svn/trunk/src/com/example/android/touchexample/TouchExampleView.java 
 */

package ca.inrs.ete.app.shopx.images;

import java.lang.ref.WeakReference;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.os.AsyncTask;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.ScaleGestureDetector;
import android.view.View;
import android.widget.ImageView;
import ca.inrs.ete.app.shopx.util.BitmapUtilities;

public class TouchExampleView extends ImageView {
	private static final int INVALID_POINTER_ID = -1;

	private float mPosX;
	private float mPosY;
	private float mLastTouchX;
	private float mLastTouchY;
	private float mScaleFactor = 1.f;
	private float mRotation = 0.f;
	private int   mActivePointerId = INVALID_POINTER_ID;

	private ScaleGestureDetector mScaleDetector;

	private Uri     mImgFile;
	private Boolean mImgLoaded = false;

	public TouchExampleView(Context context) {
		this(context, null, 0);
	}

	public TouchExampleView(Context context, AttributeSet attrs) {
		this(context, attrs, 0);
	}

	public TouchExampleView(Context context, AttributeSet attrs, int defStyle) {
		super(context, attrs, defStyle);
		mScaleDetector = new ScaleGestureDetector(context, new ScaleListener());
	}

	public void setImageFile(Uri fileName) {
		mImgFile = fileName;
		mImgLoaded = false;
	}

	public void setImageLoaded() {
		// ---  Center
		Rect r = this.getDrawable().getBounds();
		mPosX = (this.getWidth()  - r.width()) / 2;
		mPosY = (this.getHeight() - r.height()) / 2;
		// ---  Flag as loaded
		mImgLoaded = true;
	}

	@Override
	public boolean onTouchEvent(MotionEvent ev) {
		// Let the ScaleGestureDetector inspect all events.
		mScaleDetector.onTouchEvent(ev);

		final int action = ev.getAction();
		switch (action & MotionEvent.ACTION_MASK) {
		case MotionEvent.ACTION_DOWN: {
			final float x = ev.getX();
			final float y = ev.getY();

			mLastTouchX = x;
			mLastTouchY = y;
			mActivePointerId = ev.getPointerId(0);
			break;
		}

		case MotionEvent.ACTION_MOVE: {
			final int pointerIndex = ev.findPointerIndex(mActivePointerId);
			final float x = ev.getX(pointerIndex);
			final float y = ev.getY(pointerIndex);

			// Only move if the ScaleGestureDetector isn't processing a gesture.
			if (!mScaleDetector.isInProgress()) {
				final float dx = x - mLastTouchX;
				final float dy = y - mLastTouchY;

				mPosX += dx;
				mPosY += dy;

				invalidate();
			}

			mLastTouchX = x;
			mLastTouchY = y;

			break;
		}

		case MotionEvent.ACTION_UP: {
			mActivePointerId = INVALID_POINTER_ID;
			break;
		}

		case MotionEvent.ACTION_CANCEL: {
			mActivePointerId = INVALID_POINTER_ID;
			break;
		}

		case MotionEvent.ACTION_POINTER_UP: {
			final int pointerIndex = (ev.getAction() & MotionEvent.ACTION_POINTER_INDEX_MASK) 
					>> MotionEvent.ACTION_POINTER_INDEX_SHIFT;
					final int pointerId = ev.getPointerId(pointerIndex);
					if (pointerId == mActivePointerId) {
						// This was our active pointer going up. Choose a new
						// active pointer and adjust accordingly.
						final int newPointerIndex = pointerIndex == 0 ? 1 : 0;
						mLastTouchX = ev.getX(newPointerIndex);
						mLastTouchY = ev.getY(newPointerIndex);
						mActivePointerId = ev.getPointerId(newPointerIndex);
					}
					break;
		}
		}

		return true;
	}

	@Override
	public void onDraw(Canvas canvas) {
		Drawable bmp = getDrawable();
		if (! mImgLoaded) { 
			loadBitmap();
			bmp = getDrawable();
		}
/*		
		if (bmp != null) {
			if (bmp.getIntrinsicHeight() > bmp.getIntrinsicWidth())
				mRotation = 0.0f;
			else
				mRotation = 90.0f;
		}
*/
		canvas.save();
		canvas.rotate(mRotation);
		canvas.translate(mPosX, mPosY);
		canvas.scale(mScaleFactor, mScaleFactor);
		if (bmp != null) bmp.draw(canvas);
		canvas.restore();
	}

	private void loadBitmap() {
		BitmapWorkerTask bt = new BitmapWorkerTask(this);
		bt.execute(mImgFile);
	}

	private class ScaleListener extends ScaleGestureDetector.SimpleOnScaleGestureListener {
		@Override
		public boolean onScale(ScaleGestureDetector detector) {
			mScaleFactor *= detector.getScaleFactor();

			// Don't let the object get too small or too large.
			mScaleFactor = Math.max(0.1f, Math.min(mScaleFactor, 5.0f));

			invalidate();
			return true;
		}
	}
}



class BitmapWorkerTask extends AsyncTask<Uri, Void, Bitmap> 
{
	private final WeakReference<TouchExampleView> imageViewReference;
	private Uri url;
	private int imgW;
	private int imgH;

	public BitmapWorkerTask(TouchExampleView imageView) 
	{
		// Use a WeakReference to ensure the ImageView can be garbage collected
		imageViewReference = new WeakReference<TouchExampleView>(imageView);
		imgW = imageView.getWidth();
		imgH = imageView.getHeight();
	}

	@Override
	protected void onPreExecute() {
		final TouchExampleView imageView = imageViewReference.get();
		if (imageView != null) {
			imageView.setVisibility(View.INVISIBLE);
		}
	}

	// Decode image in background.
	@Override
	protected Bitmap doInBackground(Uri... params) {
		url = params[0];
		Bitmap roughBmp = BitmapUtilities.decodeResource(url, imgW, imgH);
        Bitmap finalBmp = BitmapUtilities.createScaledBitmap(roughBmp, imgW, imgH);
        roughBmp.recycle();
		return finalBmp;
	}

	// Once complete, see if ImageView is still around and set bitmap.
	@Override
	protected void onPostExecute(Bitmap bitmap) {
		if (isCancelled()) {
			bitmap = null;
		}
		if (imageViewReference != null && bitmap != null) {
			final TouchExampleView imageView = imageViewReference.get();
			if (imageView != null) {
				imageView.setImageBitmap(bitmap);
				imageView.setImageLoaded();
				imageView.setVisibility(View.VISIBLE);
			}
		}
	}
	
}

